package logic

import (
	"context"
	"errors"

	"shop-manager/internal/do"
	"shop-manager/internal/repos/contract"
	supermarket_repo "shop-manager/internal/repos/supermarket"
	"shop-manager/internal/vo"
)

// contractLogic 合同逻辑实现
//go:generate newc
type ContractLogic struct {
	contractRepo    *contract.ContractRepo
	supermarketRepo *supermarket_repo.SupermarketRepo
}


// CreateContract 创建合同
func (l *ContractLogic) CreateContract(req *vo.CreateContractReq) error {
	// 验证结束时间必须大于开始时间
	if req.EndTime.Before(req.StartTime) || req.EndTime.Equal(req.StartTime) {
		return errors.New("结束时间必须大于开始时间")
	}

	// 验证超市是否存在
	exists, err := l.contractRepo.CheckSupermarketExists(req.SupermarketID)
	if err != nil {
		return err
	}
	if !exists {
		return errors.New("超市不存在")
	}

	// 创建合同
	contract := &do.Contract{
		SupermarketID: req.SupermarketID,
		ContractType:  req.ContractType,
		StartTime:     req.StartTime,
		EndTime:       req.EndTime,
	}

	return l.contractRepo.CreateContract(contract)
}

// UpdateContract 更新合同
func (l *ContractLogic) UpdateContract(req *vo.UpdateContractReq) error {
	// 验证结束时间必须大于开始时间
	if req.EndTime.Before(req.StartTime) || req.EndTime.Equal(req.StartTime) {
		return errors.New("结束时间必须大于开始时间")
	}

	// 验证超市是否存在
	exists, err := l.contractRepo.CheckSupermarketExists(req.SupermarketID)
	if err != nil {
		return err
	}
	if !exists {
		return errors.New("超市不存在")
	}

	// 检查合同是否存在
	existingContract, err := l.contractRepo.GetContractByID(req.ID)
	if err != nil {
		return err
	}

	// 更新合同
	existingContract.SupermarketID = req.SupermarketID
	existingContract.ContractType = req.ContractType
	existingContract.StartTime = req.StartTime
	existingContract.EndTime = req.EndTime

	return l.contractRepo.UpdateContract(existingContract)
}

// DeleteContract 删除合同
func (l *ContractLogic) DeleteContract(req *vo.DeleteContractReq) error {
	// 检查合同是否存在
	_, err := l.contractRepo.GetContractByID(req.ID)
	if err != nil {
		return err
	}

	return l.contractRepo.DeleteContract(req.ID)
}

// GetContractDetail 获取合同详情
func (l *ContractLogic) GetContractDetail(req *vo.GetContractReq) (*vo.ContractRsp, error) {
	// 获取合同
	contract, err := l.contractRepo.GetContractByID(req.ID)
	if err != nil {
		return nil, err
	}

	// 获取超市名称
	supermarketName := ""
	supermarkets, _, err := l.supermarketRepo.List(context.Background(), supermarket_repo.ListParam{
		IDs: []int{int(contract.SupermarketID)},
	})
	if err == nil && len(supermarkets) > 0 {
		supermarketName = supermarkets[0].Name
	}

	// 转换为响应对象
	rsp := &vo.ContractRsp{
		ID:             contract.ID,
		SupermarketID:  contract.SupermarketID,
		ContractType:   contract.ContractType,
		SupermarketName: supermarketName,
		StartTime:      contract.StartTime,
		EndTime:        contract.EndTime,
		IsExpired:      contract.IsExpired(),
		CreatedAt:      contract.CreatedAt,
	}

	return rsp, nil
}

// GetContractList 获取合同列表
func (l *ContractLogic) GetContractList(req *vo.ListContractReq) (*vo.ListContractRsp, error) {
	// 获取合同列表
	contracts, total, err := l.contractRepo.GetContractList(req)
	if err != nil {
		return nil, err
	}

	// 收集所有超市ID
	supermarketIDs := make([]int, 0, len(contracts))
	for _, contract := range contracts {
		supermarketIDs = append(supermarketIDs, int(contract.SupermarketID))
	}

	// 批量获取超市信息
	supermarkets, _, err := l.supermarketRepo.List(context.Background(), supermarket_repo.ListParam{
		IDs:      supermarketIDs,
		PageSize: do.PageSizeNoLimit,
	})
	// 构建超市ID到名称的映射
	supermarketMap := make(map[int]string)
	if err == nil {
		for _, s := range supermarkets {
			supermarketMap[s.ID] = s.Name
		}
	}

	// 转换为响应对象列表
	list := make([]vo.ContractRsp, len(contracts))
	for i, contract := range contracts {
		// 从映射中获取超市名称
		supermarketName := supermarketMap[int(contract.SupermarketID)]

		list[i] = vo.ContractRsp{
			ID:             contract.ID,
			SupermarketID:  contract.SupermarketID,
			ContractType:   contract.ContractType,
			SupermarketName: supermarketName,
			StartTime:      contract.StartTime,
			EndTime:        contract.EndTime,
			IsExpired:      contract.IsExpired(),
			CreatedAt:      contract.CreatedAt,
		}
	}

	rsp := &vo.ListContractRsp{
		List:  list,
		Total: total,
	}

	return rsp, nil
}
